import { HttpException, HttpStatus, Injectable, BadRequestException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { JwtService } from '@nestjs/jwt';
import { getRepository, Repository } from 'typeorm';
import { ApiTypeGetReqDto, ApiTypeGetResDto } from '../types';
import { PageEnum } from '@/types/enums/page.enum';
import { Model } from 'mongoose';
import { InjectModel } from '@nestjs/mongoose';
import { ITypeEntity, ITypeEntityField } from '../types/type/superType.type';
import { syncValidate, unallow } from '@/utils/validate';
import { calculateTypeEntityHashes } from '../../editor/server/virtual-file-system/utils/calculateHashs';
import { VersionControlService } from '../../editor/server/version-control.service';
import { getTypeFileCode } from '../../editor/server/virtual-file-system/adapters/pipe/getFileCode';
import { forwardRef, Inject } from '@nestjs/common';

@Injectable()
export class TypeService {
  constructor(
    @InjectModel('type') private typeModel: Model<ITypeEntity>,
    @Inject(forwardRef(() => VersionControlService))
    private versionControlService: VersionControlService,
  ) {}

  async save(typeItem: ITypeEntity, user_id: number, shop_id: number) {
    try {
      await syncValidate(typeItem, {
        name: {
          required: true,
          enable: (values) => !['api', 'api-import'].includes(values.type),
        },
        desc: {
          required: true,
          enable: (values) => !['api', 'vo'].includes(values.type),
        },
        fields: {
          type: 'array',
          required: false,
        },
      });
    } catch (e) {
      throw new HttpException(e.message, HttpStatus.BAD_REQUEST);
    }
    const data = unallow(typeItem, ['create_time', 'update_time', 'userId']);
    if (typeItem._id) {
      data.update_time = Date.now();
      const updateRes = await this.typeModel.updateOne(
        { _id: typeItem._id },
        data,
      );
      return {
        _id: typeItem._id,
        ...data,
      };
    } else {
      data.userId = user_id;
      data.teamId = shop_id;
      data.create_time = Date.now();
      data.update_time = Date.now();
      const createdCat = new this.typeModel(data);
      return createdCat.save();
    }
  }

  /**
   * 保存类型实体（供 Controller 和 VFS Service 复用）
   * @param typeData 类型数据
   * @param options 保存选项
   * @returns 保存后的类型实体
   */
  async saveType(
    typeData: Partial<ITypeEntity> & { _id?: string },
    options: {
      userId: number;
      teamId: number;
      skipValidation?: boolean;
      skipPermissionCheck?: boolean;
      skipHashCalculation?: boolean;
      existType?: ITypeEntity;
    },
  ): Promise<ITypeEntity> {
    const { _id, ...params } = typeData;
    const { userId, teamId, skipValidation, existType: providedExistType } = options;

    // 获取现有类型实体
    let existType = providedExistType;
    let finalId = _id;

    // 如果没有 _id，尝试根据 unikey 查找现有类型
    if (!finalId && params.unikey) {
      let where = {};
      if (params.type === 'api') {
        where = {
          uri: params.uri,
          method: params.method,
          type: params.type,
          projectId: params.projectId,
        };
      } else if (params.type === 'vo') {
        where = {
          name: params.name,
          type: params.type,
          projectId: params.projectId,
        };
      } else if (params.type === 'cloud_function') {
        where = {
          name: params.name,
          type: params.type,
          projectId: params.projectId,
        };
      } else if (params.type === 'action') {
        where = {
          name: params.name,
          type: params.type,
          projectId: params.projectId,
        };
      } else if (params.type === 'folder') {
        where = {
          folderPath: params.folderPath,
          type: params.type,
          projectId: params.projectId,
        };
      } else {
        where = {
          unikey: params.unikey,
          projectId: params.projectId,
        };
      }
      const foundType = await this.typeModel.findOne(where).lean();
      if (foundType) {
        finalId = foundType._id;
        existType = foundType;
      }
    }

    // 如果有 _id 但没有传入 existType，则查询
    if (finalId && !existType) {
      existType = await this.typeModel.findById(finalId).lean();
    }

    // 业务规则验证
    if (
      params.type === 'vo' &&
      typeof params.fields !== 'undefined' &&
      params.fields.length === 0
    ) {
      throw new HttpException('字段不能为空', HttpStatus.BAD_REQUEST);
    }

    // 保存哈希计算结果用于历史记录
    let typeHash: string | undefined;
    let typeContent: string | null = null;
    let typePath: string | null = null;

    // 如果没有跳过哈希计算且不是文件夹类型
    if (!options.skipHashCalculation && params.type !== 'folder') {
      try {
        // 构建完整的类型实体数据用于计算哈希
        const typeEntityForHash: ITypeEntity = {
          ...existType,
          ...params,
          cases: params.cases || [],
        } as ITypeEntity;

        const res = await calculateTypeEntityHashes(typeEntityForHash);
        if (res.hash) {
          params.hash = res.hash;
          params.path = res.path;
          params.size = res.size;

          // 🆕 保存哈希和内容用于历史记录
          typeHash = res.hash;
          typePath = res.path;
          typeContent = await getTypeFileCode(res.typeItem); // 🆕 保存类型代码
        }
      } catch(e) {
        console.error('计算类型哈希失败:', e);
      }
    }

    // 更新现有类型实体
    if (finalId && existType) {
      const updateData = {
        ...params,
        update_time: Date.now(),
        cases: params.cases ? JSON.stringify(params.cases) : existType.cases,
      };

      const updateRes = await this.typeModel.updateOne(
        { _id: finalId },
        updateData,
      );

      // 🆕 记录类型文件变更历史
      if (!options.skipHashCalculation && typeHash && typeContent) {
        const hashChanged = existType?.hash !== typeHash;

        if (hashChanged) {
          try {
            // 获取旧的类型内容
            let previousTypeContent = '';
            const isFirstVersion = !existType || !existType.hash;

            if (!isFirstVersion && existType.hash !== typeHash) {
              previousTypeContent = await this.versionControlService.getLatestFileContent(
                existType.projectId,
                typePath,
              ) || '';
            }

            console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
            console.log('📋 [类型历史记录] 开始记录');
            console.log('  文件路径:', typePath);
            console.log('  类型ID:', finalId);
            console.log('  是否首次:', isFirstVersion);
            console.log('  旧 hash:', existType?.hash || 'none');
            console.log('  新 hash:', typeHash);
            console.log('  类型内容长度:', typeContent.length);
            console.log('  旧类型内容长度:', previousTypeContent.length);
            console.log('  操作类型:', isFirstVersion ? 'add' : 'modify');
            console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');

            await this.versionControlService.recordFileChange({
              projectId: existType.projectId,
              path: typePath,
              action: isFirstVersion ? 'add' : 'modify',
              content: typeContent,
              previousContent: previousTypeContent,
              contentHash: typeHash,
              userId,
            });

            console.log(`✅ [类型历史记录] 记录成功: ${typePath}`);
          } catch (error) {
            console.error(`❌ [类型历史记录] 记录失败: ${typePath}`, error);
          }
        }
      }

      return {
        _id: finalId,
        ...existType,
        ...updateData,
      } as ITypeEntity;
    } else {
      // 创建新类型实体
      const createData = {
        ...params,
        userId,
        teamId,
        create_time: Date.now(),
        update_time: Date.now(),
        cases: params.cases ? JSON.stringify(params.cases) : '[]',
      };

      if (params.type === 'code' && !params.language) {
        throw new BadRequestException('请选择语言');
      }

      const createdType = new this.typeModel(createData);
      const savedType = await createdType.save();

      // 🆕 记录新类型的历史
      if (!options.skipHashCalculation && typeHash && typeContent) {
        try {
          console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
          console.log('📋 [新类型历史记录] 开始记录');
          console.log('  文件路径:', typePath);
          console.log('  类型ID:', savedType._id);
          console.log('  类型 hash:', typeHash);
          console.log('  类型内容长度:', typeContent.length);
          console.log('  操作类型: add');
          console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');

          await this.versionControlService.recordFileChange({
            projectId: savedType.projectId,
            path: typePath,
            action: 'add',
            content: typeContent,
            contentHash: typeHash,
            userId,
          });

          console.log(`✅ [新类型历史记录] 记录成功: ${typePath}`);
        } catch (error) {
          console.error(`❌ [新类型历史记录] 记录失败: ${typePath}`, error);
        }
      }

      return savedType;
    }
  }

  async getType(
    params: ApiTypeGetReqDto,
    userId: number,
    teamId: number,
  ): Promise<ApiTypeGetResDto> {
    const {
      currentPage = PageEnum.PAGE_NUMBER,
      pageSize = PageEnum.PAGE_SIZE,
      count,
      name,
      fkId,
      projectId,
      fileName,
      _id,
      ids,
      type,
      types,
      condition,
      select,
      afterTime,
    } = params;
    const query = this.typeModel;
    const where = {
      // teamId,
      ...condition,
    };
    if (fileName) {
      Object.assign(where, {
        fileName,
      });
    }
    if (projectId) {
      Object.assign(where, {
        projectId,
      });
    }
    if (_id) {
      Object.assign(where, {
        _id,
      });
    }
    if (name) {
      Object.assign(where, {
        name,
      });
    }
    if (type) {
      Object.assign(where, {
        type,
      });
    }
    if (types) {
      Object.assign(where, {
        type: { $in: types },
      });
    }
    if (ids) {
      Object.assign(where, {
        _id: { $in: ids },
      });
    }
    if (fkId) {
      Object.assign(where, {
        fkId,
      });
    }
    if (afterTime) {
      where.update_time = {
        $gt: afterTime,
      };
    }

    if ((!projectId && !fkId) || !ids || !_id) {
      // 表示查询公开资源
      // @TODO: 需要增加权限限制
    }
    const data = await query
      .where(where)
      .select(select || null)
      .skip((currentPage - 1) * pageSize)
      .limit(pageSize)
      .find()
      .exec();
    const isFetched: { [propName: string]: ITypeEntity } = {};
    // 递归查询引用类型
    const func = async (typeItem: ITypeEntity) => {
      if (isFetched[typeItem._id]) return;
      isFetched[typeItem._id] = typeItem;
      const computeFields = async (fields: ITypeEntityField[]) => {
        if (fields && fields.length > 0) {
          for (let x = 0; x < fields.length; x++) {
            const field = fields[x];
            // 判断 field.import 是否是 ObjectId 字符串
            let importIsNotObjectId = true;
            if (typeof field.import === 'string' && field.import.length === 24) {
              importIsNotObjectId = false;
            }
            const queryCondition = !importIsNotObjectId
              ? { _id: field.import }
              : { name: field.import };

            if (field.import) {
              if (!isFetched[field.import]) {
                const importTypeItem = await query.findOne(queryCondition).exec();
                isFetched[field.import] = importTypeItem;
                // console.log(field.import);
                if (importTypeItem) {
                  data.push(importTypeItem);
                  field.importEntity = importTypeItem;
                  // 修复Import引用为模型name字符串的问题
                  if (importIsNotObjectId) {
                    field.import = importTypeItem._id;
                  }
                  await func(importTypeItem);
                }
              } else {
                // 防止循环引用
                field.importEntity = JSON.parse(
                  JSON.stringify(isFetched[field.import]),
                );
              }
            }
            if (field.apiImport) {
              const importTypeItem = await query.findById(field.apiImport);
              if (importTypeItem) {
                field.apiImportEntity = importTypeItem;
                data.push(importTypeItem);
                await func(importTypeItem);
              }
            }
          }
        }
      };
      if (typeItem.fields?.length > 0) {
        await computeFields(typeItem.fields);
      }
      if (typeItem.params?.length > 0) {
        await computeFields(typeItem.params);
      }
      // 转换
      if (typeItem.cases && typeof typeItem.cases === 'string') {
        typeItem.cases = JSON.parse(typeItem.cases);
      }
    };
    for (let i = 0; i < data.length; i++) {
      const typeItem = data[i];
      await func(typeItem);
    }
    const total = count ? await this.typeModel.where(where).count().exec() : 0;
    return {
      currentPage,
      pageSize,
      data,
      total,
    };
  }
}
